﻿/* To Do Section
 * TODO: Auto Server Reload (Done and seems to work. Watch it still though. Don't close before it works for some time)
 * TODO: LocalApplicationOptions: Insert Newline
 * TODO: ActionLogger Class with FIFO Buffer of configurable size. ?Start with 500 entries?
 * TODO: UpdateSeed.php Auswertung.
 */




using System;
using System.Collections.Generic;
using CSharp.Libs.Koc.KernelViewModels;
using CSharp.Libs.Koc.KernelModels.ItemClasses;
using CSharp.Libs.ExceptionHandling;
using CSharp.Libs.Koc;
using CSharp.Libs.Misc;
using CSharp.Libs.Koc.KernelModels;
using System.Collections;



namespace CSharp.Libs.Koc
{
    public class Kernel
    {
        #region declarations
        private ExceptionCollector _EC = null;
        private LocalApplicationOptions _LAO = null;
        private TrafficMonitor _TM = null;
        private UserValidator _UV = null;
        private URLHolder _UH = null;
        private DatabaseOperations _DBOps = null;
        private KocReloader _AKR = null;
        private BaseSeedViewModel _BSVM = null;
        private InfoViewModel _IVM = null;

        private Dictionary<Int32, MarchItem> _dictMarches = null;

        private Int32 _intInternalUID = 1;

        public enum VariableTypes
        {
            String = 1,
            Int32,
            Int64,
            Double,
            Boolean
        }
        #endregion



        #region constructor / terminator
        public Kernel()
        {
            _EC = new ExceptionCollector();
            _LAO = new LocalApplicationOptions();

            _CheckOptionsFile();

            _TM = new TrafficMonitor(this);
            _UV = new UserValidator(this);
            _UH = new URLHolder(_EC);
            _BSVM = new BaseSeedViewModel(this);
            _DBOps = new DatabaseOperations(this);
            _AKR = new KocReloader(this);

            _dictMarches = new Dictionary<Int32, MarchItem>();

            _DBOps.InitDb(_LAO.GetOption(constants.LAO_AUTOKOC_DB_FILE_NAME));
        }

        ~Kernel()
        {
            _dictMarches = null;

            _AKR = null;
            _DBOps = null;
            _BSVM = null;
            _UH = null;
            _UV = null;
            _TM = null;
            _LAO = null;
            _EC.Dispose();
            _EC = null;
        }
        #endregion



        #region private functions
        private void _CheckOptionsFile()
        {
            try
            {
                if (_LAO.OptionsCount == 0)
                {
                    _CreateDefaultOptions();
                }
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }
        }

        /// <summary>_CreateDefaultOptions
        /// 
        /// </summary>
        /// <history>29.04.2011 added custom servers</history>
        private void _CreateDefaultOptions()
        {
            try
            {
                //disable event
                _LAO.DoThrowOptionsChangedEvent = false;

                _LAO.SetComment("Working Facebook URL including http");
                _LAO.SetOption(constants.LAO_FACEBOOK_URL, "http://www.facebook.de");
                _LAO.SetComment("Main Source php Command");
                _LAO.SetOption(constants.LAO_RECOGNIZE_STRING_PHP_MAIN_SRC, "main_src.php?");
                _LAO.SetOption(constants.LAO_SEEK_STRING_MAIN_SRC_SEED_START, "var seed");
                _LAO.SetOption(constants.LAO_SEEK_STRING_MAIN_SRC_SEED_END, ";var ");
                _LAO.SetOption(constants.LAO_RECOGNIZE_STRING_FB_SIG, "fb_sig");
                _LAO.SetOption(constants.LAO_KOC_RELOAD_URL, "http://apps.facebook.com/kingdomsofcamelot/?s=");
                _LAO.SetOption(constants.LAO_AUTOKOC_DB_FILE_NAME, "AutoKoc.s3db");
                _LAO.SetOption(constants.LAO_DEFAULT_SERVER_ID, "1");
                _LAO.SetOption(constants.LAO_KOC_RELOAD_TIMEOUT, "30");
                _LAO.SetOption(constants.LAO_KOC_CUSTOM_SERVER_1, "0");
                _LAO.SetOption(constants.LAO_KOC_CUSTOM_SERVER_2, "0");
                _LAO.SetOption(constants.LAO_KOC_CUSTOM_SERVER_3, "0");
                _LAO.SetOption(constants.LAO_KOC_CUSTOM_SERVER_4, "0");
                _LAO.SetOption(constants.LAO_KOC_CUSTOM_SERVER_5, "0");

                //reanable event
                _LAO.DoThrowOptionsChangedEvent = true;
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }
        }

        /// <summary>_DataIsValid
        ///     returns true if all data is valid
        /// </summary>
        /// <returns></returns>
        private Boolean _DataIsValid()
        {
            try
            {
                return _UH.URLGetChat.URLMaybeValid && _TM.UserIsValid && _BSVM.JsonSeed != null;
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }

            return false;
        }

        /// <summary>_GetHashtableValue</summary>
        /// <param name="HT"></param>
        /// <param name="Key"></param>
        /// <param name="ReturnType"></param>
        /// <returns></returns>
        /// <history>15.05.2011</history>
        private dynamic _GetHashtableValue(
            Hashtable HT,
            String Key,
            VariableTypes ReturnType)
        {
            try
            {
                return _GetObjectValue((Object)HT[Key], ReturnType);
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }

            return null;
        }

        /// <summary>_GetObjectValue</summary>
        /// <param name="objValue"></param>
        /// <param name="ReturnType"></param>
        /// <returns></returns>
        /// <history>09.06.2011</history>
        private dynamic _GetObjectValue(
            Object objValue,
            VariableTypes ReturnType)
        {
            try
            {
                switch (ReturnType)
                {
                    case VariableTypes.String:
                        if (objValue == null)
                        {
                            return "";
                        }
                        return objValue.ToString();

                    case VariableTypes.Double:
                        if (objValue == null)
                        {
                            return (Double)0;
                        }
                        Double dblRetVal = 0;
                        Double.TryParse(objValue.ToString(), out dblRetVal);
                        return dblRetVal;

                    case VariableTypes.Int32:
                        if (objValue == null)
                        {
                            return (Int32)0;
                        }
                        Int32 int32RetVal = 0;
                        Int32.TryParse(objValue.ToString(), out int32RetVal);
                        return int32RetVal;

                    case VariableTypes.Int64:
                        if (objValue == null)
                        {
                            return (Int64)0;
                        }
                        Int64 int64RetVal = 0;
                        Int64.TryParse(objValue.ToString(), out int64RetVal);
                        return int64RetVal;

                    case VariableTypes.Boolean:
                        if (objValue == null)
                        {
                            return false;
                        }
                        Boolean fRetVal = false;
                        Boolean.TryParse(objValue.ToString(), out fRetVal);
                        return fRetVal;
                }
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }

            return null;
        }

        /// <summary>_ReturnHashtableOk</summary>
        /// <param name="htReturn"></param>
        /// <returns></returns>
        /// <history>04.07.2011</history>
        private Boolean _ReturnHashtableOk(
            Hashtable htReturn)
        {
            try
            {
                if (htReturn != null)
                {
                    if (htReturn[constants.KEY_OK] != null)
                    {
                        if (htReturn[constants.KEY_OK] is Boolean)
                        {
                            return (Boolean)htReturn[constants.KEY_OK];
                        }
                        else if (htReturn[constants.KEY_OK] is String)
                        {
                            return Boolean.Parse(htReturn[constants.KEY_OK].ToString());
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }

            return false;
        }
        #endregion



        #region interface
        #region properties
        public ExceptionCollector EC
        {
            get
            {
                return _EC;
            }
        }

        public LocalApplicationOptions LAO
        {
            get
            {
                return _LAO;
            }
        }

        public TrafficMonitor TM
        {
            get
            {
                return _TM;
            }
        }

        public UserValidator UV
        {
            get
            {
                return _UV;
            }
        }

        public URLHolder UH
        {
            get
            {
                return _UH;
            }
        }

        public DatabaseOperations DBOps
        {
            get
            {
                return _DBOps;
            }
        }

        public KocReloader AKR
        {
            get
            {
                return _AKR;
            }
        }

        public BaseSeedViewModel BSVM
        {
            get
            {
                return _BSVM;
            }
        }

        public InfoViewModel IVM
        {
            get
            {
                return _IVM;
            }
        }

        public Dictionary<Int32, MarchItem> Marches
        {
            get
            {
                return _dictMarches;
            }
        }

        public Boolean DataIsValid
        {
            get
            {
                return _DataIsValid();
            }
        }

        public Int32 InternalUID
        {
            get
            {
                return _intInternalUID++;
            }
        }
        #endregion

        #region methods
        /// <summary>conv_Timestamp2Date
        /// 
        /// </summary>
        /// <param name="Timestamp"></param>
        /// <returns></returns>
        /// <history>24.04.2011 (taken off http://dotnet-snippets.de/dns/unix-timestamp-in-datum-wandeln-SID164.aspx)</history>
        public string conv_Timestamp2Date(
            Int32 Timestamp)
        {
            //  gerechnet wird ab der UNIX Epoche
            System.DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
            // den Timestamp addieren           
            dateTime = dateTime.AddSeconds(Timestamp);
            string Date = dateTime.ToShortDateString() + ", " + dateTime.ToShortTimeString();
            //MessageBox.Show(Date);
            return Date;
        }

        /// <summary>conv_Date2Timestamp
        /// 
        /// </summary>
        /// <param name="Timestamp"></param>
        /// <returns></returns>
        /// <history>24.04.2011 (taken off http://dotnet-snippets.de/dns/unix-timestamp-in-datum-wandeln-SID164.aspx)</history>
        public int conv_Date2Timestamp(
            DateTime date)
        {
            DateTime date1 = new DateTime(1970, 1, 1);  //Refernzdatum (festgelegt)
            TimeSpan ts = new TimeSpan(date.Ticks - date1.Ticks);  // das Delta ermitteln
            // Das Delta als gesammtzahl der sekunden ist der Timestamp
            return (Convert.ToInt32(ts.TotalSeconds));
        }

        /// <summary>GetCurrentValue</summary>
        /// <param name="RefTimeStamp"></param>
        /// <param name="RefValue"></param>
        /// <param name="Usage"></param>
        /// <returns></returns>
        /// <history>26.04.2011</history>
        /// <history>05.05.2011 changed calculation</history>
        public Double GetCurrentValue(
            Int32 RefTimestamp,
            SeedCityResourceItem SRI)
        {
            try
            {
                if (SRI.Usage > 0)
                {
                    Int32 CurrentTimestamp = conv_Date2Timestamp(DateTime.Now);

                    if (CurrentTimestamp > RefTimestamp)
                    {
                        Double Diff = (((Double)SRI.Production - (Double)SRI.Usage) / (Double)3600) * (CurrentTimestamp - RefTimestamp);
                        return (Double)SRI.Value + Diff;
                    }
                }
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }

            return (Double)SRI.Value;
        }

        public dynamic GetHashtableValue(
           Hashtable HT,
           String Key,
           VariableTypes ReturnType)
        {
            return _GetHashtableValue(HT, Key, ReturnType);
        }

        public dynamic GetObjectValue(
            Object objValue,
            VariableTypes ReturnType)
        {
            return _GetObjectValue(objValue, ReturnType);
        }

        /// <summary>GetInt32</summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        /// <history>05.06.2011</history>
        public Int32 GetInt32(
            object Value)
        {
            try
            {
                Int32 retVal = 0;

                if (Int32.TryParse(Value.ToString(), out retVal))
                {
                    return retVal;
                }
            }
            catch (Exception ex)
            {
                _EC.AddException(ex, this.ToString(), _EC.Tools.GetCurrentMethodName());
            }

            return -1;
        }

        public Boolean ReturnHashtableOk(
            Hashtable htReturn)
        {
            return _ReturnHashtableOk(htReturn);
        }
        #endregion
        #endregion
    }
}
